home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / m4-1_0_3.lha / m4-1.0.3 / macro.c < prev    next >
C/C++ Source or Header  |  1992-12-19  |  8KB  |  288 lines

  1. /*
  2.  * GNU m4 -- A simple macro processor
  3.  * Copyright (C) 1989-1992 Free Software Foundation, Inc.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /*
  21.  * This file contains the functions, that performs the basic argument
  22.  * parsing and macro expansion.
  23.  */
  24.  
  25. #include "m4.h"
  26.  
  27. static void expand_token ();
  28. static void expand_macro ();
  29.  
  30. /* Current recursion level in expand_macro ().  */
  31. int expansion_level = 0;
  32.  
  33. /* The number of the current call of expand_macro ().  */
  34. static int macro_call_id = 0;
  35.  
  36. /*
  37.  * This function read all input, and expands each token, one at a time.
  38.  */
  39. void
  40. expand_input (void)
  41. {
  42.   token_type t;
  43.   token_data td;
  44.  
  45.   while ((t = next_token (&td)) != TOKEN_EOF)
  46.     expand_token ((struct obstack *) NULL, t, &td);
  47. }
  48.  
  49.  
  50. /*
  51.  * Expand one token, according to its type.  Potential macro names
  52.  * (TOKEN_WORD) are looked up in the symbol table, to see if they have a
  53.  * macro definition.  If they have, they are expanded as macroes,
  54.  * otherwise the text are just copied to the output.
  55.  */
  56. static void
  57. expand_token (struct obstack *obs, token_type t, token_data *td)
  58. {
  59.   symbol *sym;
  60.  
  61.   switch (t)
  62.     {                /* TOKSW */
  63.     case TOKEN_EOF:
  64.     case TOKEN_MACDEF:
  65.       break;
  66.     case TOKEN_SIMPLE:
  67.     case TOKEN_STRING:
  68.       shipout_text (obs, TOKEN_DATA_TEXT (td));
  69.       break;
  70.     case TOKEN_WORD:
  71.       sym = lookup_symbol (TOKEN_DATA_TEXT (td), SYMBOL_LOOKUP);
  72.       if (sym == NULL || SYMBOL_TYPE (sym) == TOKEN_VOID)
  73.     shipout_text (obs, TOKEN_DATA_TEXT (td));
  74.       else
  75.     expand_macro (sym);
  76.       break;
  77.     default:
  78.       internal_error ("Bad token type in expand_token ()");
  79.       break;
  80.     }
  81. }
  82.  
  83.  
  84. /*
  85.  * This function parses one argument to a macro call.  It expects the
  86.  * first left parenthesis, or the separating comma to have been read by
  87.  * the caller.  It skips leading whitespace, and reads and expands
  88.  * tokens, until it finds a comma or an right parenthesis at the same
  89.  * level of parentheses.  It returns a flag indicating whether the
  90.  * argument read are the last for the active macro call.  The argument
  91.  * are build on the obstack OBS, indirectly through expand_token ().
  92.  */
  93. static boolean
  94. expand_argument (struct obstack *obs, token_data *argp)
  95. {
  96.   token_type t;
  97.   token_data td;
  98.   char *text;
  99.   int paren_level;
  100.  
  101.   TOKEN_DATA_TYPE (argp) = TOKEN_VOID;
  102.  
  103.   /* Skip leading white space.  */
  104.   do
  105.     {
  106.       t = next_token (&td);
  107.     }
  108.   while (t == TOKEN_SIMPLE && isspace (*TOKEN_DATA_TEXT (&td)));
  109.  
  110.   paren_level = 0;
  111.  
  112.   while (1)
  113.     {
  114.  
  115.       switch (t)
  116.     {            /* TOKSW */
  117.     case TOKEN_SIMPLE:
  118.       text = TOKEN_DATA_TEXT (&td);
  119.       if ((*text == ',' || *text == ')') && paren_level == 0)
  120.         {
  121.  
  122.           /* The argument MUST be finished, whether we want it or not.  */
  123.           obstack_1grow (obs, '\0');
  124.           text = obstack_finish (obs);
  125.  
  126.           if (TOKEN_DATA_TYPE (argp) == TOKEN_VOID)
  127.         {
  128.           TOKEN_DATA_TYPE (argp) = TOKEN_TEXT;
  129.           TOKEN_DATA_TEXT (argp) = text;
  130.         }
  131.           return (boolean) (*TOKEN_DATA_TEXT (&td) == ',');
  132.         }
  133.  
  134.       if (*text == '(')
  135.         paren_level++;
  136.       else if (*text == ')')
  137.         paren_level--;
  138.       expand_token (obs, t, &td);
  139.       break;
  140.     case TOKEN_EOF:
  141.       fatal ("EOF in argument list");
  142.       break;
  143.     case TOKEN_WORD:
  144.     case TOKEN_STRING:
  145.       expand_token (obs, t, &td);
  146.       break;
  147.     case TOKEN_MACDEF:
  148.       if (obstack_object_size (obs) == 0)
  149.         {
  150.           TOKEN_DATA_TYPE (argp) = TOKEN_FUNC;
  151.           TOKEN_DATA_FUNC (argp) = TOKEN_DATA_FUNC (&td);
  152.           TOKEN_DATA_FUNC_TRACED (argp) = TOKEN_DATA_FUNC_TRACED (&td);
  153.         }
  154.       break;
  155.     default:
  156.       internal_error ("Bad token type in expand_argument ()");
  157.       break;
  158.     }
  159.  
  160.       t = next_token (&td);
  161.     }
  162. }
  163.  
  164. /*
  165.  * Collect all the arguments to a call of the macro SYM.  The arguments
  166.  * are stored on the obstack ARGUMENTS and a table of pointers to the
  167.  * arguments on the obstack ARGPTR.
  168.  */
  169. static void
  170. collect_arguments (symbol *sym, struct obstack *argptr,
  171.            struct obstack *arguments)
  172. {
  173.   int ch;            /* lookahead for ( */
  174.   token_data td;
  175.   token_data *tdp;
  176.   boolean more_args;
  177.   boolean groks_macro_args = SYMBOL_MACRO_ARGS (sym);
  178.  
  179.   TOKEN_DATA_TYPE (&td) = TOKEN_TEXT;
  180.   TOKEN_DATA_TEXT (&td) = SYMBOL_NAME (sym);
  181.   tdp = (token_data *) obstack_copy (arguments, &td, sizeof (td));
  182.   obstack_grow (argptr, &tdp, sizeof (tdp));
  183.  
  184.   ch = peek_input ();
  185.   if (ch == '(')
  186.     {
  187.       next_token (&td);        /* gobble parenthesis */
  188.       do
  189.     {
  190.       more_args = expand_argument (arguments, &td);
  191.  
  192.       if (!groks_macro_args && TOKEN_DATA_TYPE (&td) == TOKEN_FUNC)
  193.         {
  194.           TOKEN_DATA_TYPE (&td) = TOKEN_TEXT;
  195.           TOKEN_DATA_TEXT (&td) = "";
  196.         }
  197.       tdp = (token_data *) obstack_copy (arguments, &td, sizeof (td));
  198.       obstack_grow (argptr, &tdp, sizeof (tdp));
  199.     }
  200.       while (more_args);
  201.     }
  202. }
  203.  
  204.  
  205.  
  206. /*
  207.  * The actual call of a is handled by call_macro ().  call_macro () is
  208.  * passed a symbol SYM, whose type are used to call either a builtin
  209.  * function, or the user macro expansion function expand_user_macro ()
  210.  * (lives in builtin.c).  There are ARGC arguments to the call, stored
  211.  * in the ARGV table.  The expansion is left on the obstack EXPANSION.
  212.  * Macro tracing are also handled here.
  213.  */
  214. void
  215. call_macro (symbol *sym, int argc, token_data **argv,
  216.          struct obstack *expansion)
  217. {
  218.   switch (SYMBOL_TYPE (sym))
  219.     {
  220.     case TOKEN_FUNC:
  221.       (SYMBOL_FUNC (sym)) (expansion, argc, argv);
  222.       break;
  223.     case TOKEN_TEXT:
  224.       expand_user_macro (expansion, sym, argc, argv);
  225.       break;
  226.     default:
  227.       internal_error ("Bad symbol type in call_macro ()");
  228.       break;
  229.     }
  230. }
  231.  
  232. /*
  233.  * The macro expansion is handled by expand_macro ().  It parses the
  234.  * arguments, using collect_arguments (), and builds a table of pointers
  235.  * to the arguments.  The arguments themselves are stored on a local
  236.  * obstack.  Expand_macro () uses call_macro () to do the call of the
  237.  * macro.
  238.  *
  239.  * Expand_macro () is potentially recursive, since it calls
  240.  * expand_argument (), which might call expand_token (), which might call
  241.  * expand_macro ().
  242.  */
  243. static void
  244. expand_macro (symbol *sym)
  245. {
  246.   struct obstack arguments;
  247.   struct obstack argptr;
  248.   token_data **argv;
  249.   int argc;
  250.   struct obstack *expansion;
  251.   char *expanded;
  252.   boolean traced;
  253.   int my_call_id;
  254.  
  255.   expansion_level++;
  256.   macro_call_id++;
  257.  
  258.   my_call_id = macro_call_id;
  259.  
  260.   traced = (debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym);
  261.  
  262.   obstack_init (&argptr);
  263.   obstack_init (&arguments);
  264.  
  265.   if (traced && (debug_level & DEBUG_TRACE_CALL))
  266.     trace_prepre (SYMBOL_NAME (sym), my_call_id);
  267.  
  268.   collect_arguments (sym, &argptr, &arguments);
  269.  
  270.   argc = obstack_object_size (&argptr) / sizeof (token_data *);
  271.   argv = (token_data **) obstack_finish (&argptr);
  272.  
  273.   if (traced)
  274.     trace_pre (SYMBOL_NAME (sym), my_call_id, argc, argv);
  275.  
  276.   expansion = push_string_init ();
  277.   call_macro (sym, argc, argv, expansion);
  278.   expanded = push_string_finish ();
  279.  
  280.   if (traced)
  281.     trace_post (SYMBOL_NAME (sym), my_call_id, argc, argv, expanded);
  282.  
  283.   --expansion_level;
  284.  
  285.   obstack_free (&arguments, NULL);
  286.   obstack_free (&argptr, NULL);
  287. }
  288.